package com.hzjh.base.web.core

import android.graphics.Bitmap
import android.net.Uri
import android.net.http.SslError
import android.webkit.RenderProcessGoneDetail
import android.webkit.SslErrorHandler
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import com.hzjh.base.log.JHLogger
import com.hzjh.base.style.view.dialog.ConfirmDialog
import com.hzjh.base.utils.other.ActivityStackManage
import com.hzjh.base.web.util.JHWebViewPool
import com.hzjh.base.web.util.WebCacheUtil
import java.net.URLDecoder

class BaseWebViewClient(private val mWebSettings: WebSettings) : WebViewClient() {
    private val TAG = "GuangWebView"
    var mListener: JHWebView.OnWebChangeListener? = null
    var ifUseCache: Boolean = true
    //记录埋点的URL 包括重定向的URL在内
    var loadSpmUrlMap:HashMap<String,Map<String,String>> = hashMapOf()
    var errorDialog:ConfirmDialog?=null
    override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
        JHLogger.d( "onPageStarted --- $url")
        mListener?.onWebLoadStart(url)
    }

    override fun onPageFinished(view: WebView?, url: String?) {
        try {
            if (!mWebSettings.loadsImagesAutomatically) {
                mWebSettings.loadsImagesAutomatically = true
            }
            JHLogger.d( "onPageFinished --- $url")
            if (url == "about:blank") {
                //释放历史页面
                view?.clearHistory()
                view?.stopLoading()
                if (view is JHWebView) {
                    //回收webview
                    JHWebViewPool.getInstance().recycle(view)
                }
            } else {
                mListener?.onWebLoadFinish(url)

                //埋点上报
                var params = loadSpmUrlMap[url] ?: loadSpmUrlMap[URLDecoder.decode(url, "UTF-8")]
                if (params == null && url != null && url.contains("/?")) {
                    JHLogger.d(  "链接存在--- /? --- $url")
                    val targetUrl = url.replace("/?", "?")
                    params = loadSpmUrlMap[targetUrl] ?: loadSpmUrlMap[URLDecoder.decode(
                        targetUrl,
                        "UTF-8"
                    )]
                }
                params?.let {
                    mListener?.onWebLoadStatus(it)
                    JHLogger.d("状态 ---- $it")

                    //上报后删除
                    loadSpmUrlMap.remove(url)
                    loadSpmUrlMap.remove(URLDecoder.decode(url, "UTF-8"))
                    val targetUrl = url?.replace("/?", "?")
                    loadSpmUrlMap.remove(targetUrl)
                    loadSpmUrlMap.remove(URLDecoder.decode(targetUrl, "UTF-8"))
                }
            }
        }catch (e:Exception){
            JHLogger.d(  "onPageFinished --- $e")
        }
    }

    //在当前的webview中跳转到新的url
    override fun shouldOverrideUrlLoading(view: WebView, url: String?): Boolean {
        mListener?.onInnerLinkChecked(url)

        val scheme = Uri.parse(url).scheme ?: return false
        when (scheme) {
            "http", "https" -> view.loadUrl(url!!)
            // 处理其他协议
            //"weixin" ->  {}
            //"alipays" ->  {}
        }
        return true //true拦截 false不拦截
    }

    override fun onReceivedError(
        view: WebView?,
        request: WebResourceRequest?,
        error: WebResourceError?
    ) {
        super.onReceivedError(view, request, error)
        mListener?.onWebLoadError()
        JHLogger.e("加载H5错误 ${error?.errorCode}---${error?.description}")
        if(error?.description=="net::ERR_CONNECTION_CLOSED"){
            //加载失败弹框
            if(errorDialog==null) {
                errorDialog = ConfirmDialog.Builder(ActivityStackManage.currentActivity())
                    .setTitle("")
                    .setMessage("net::ERR_CONNECTION_CLOSED\n\n" + "Please reload")
                    .setSureButton("Reload") { dialog, _ ->
                        //重新加载
                        view?.reload()
                        dialog.dismiss()
                    }.setCanCancel(false).create()
            }
            errorDialog?.show()
        }
    }

    override fun onReceivedHttpError(
        view: WebView?,
        request: WebResourceRequest?,
        errorResponse: WebResourceResponse?
    ) {
        super.onReceivedHttpError(view, request, errorResponse)

        val loadUrl: String = request?.url.toString()
        if (loadUrl.endsWith("favicon.ico")) {
            //所谓favicon，即Favorites Icon的缩写，是指显示在浏览器收藏夹、地址栏和标签标题前面的个性化图标。 以图标的方式区别不同的网站
            //favicon.ico 不是必要的，当您使用浏览器浏览不同站点时，浏览器将自动发送请求。 如果您的浏览器收到有效 favicon.ico 文件，将显示此图标。 如果未收到，则不会显示特殊图标，会报404错误，并且会记录到错误日志中，所以最好的设置
            return
        }
        JHLogger.e(errorResponse.toString())
        mListener?.let {listener->
            //查找是否存在需要上报加载的H5地址
            if(loadSpmUrlMap.containsKey(loadUrl)){
                var location= ""
                if (errorResponse?.responseHeaders?.containsKey("Location") == true) {
                    location = errorResponse.responseHeaders["Location"].toString()
                }
                val params = mapOf("url" to loadUrl,"code" to "${errorResponse?.statusCode}",
                    "location" to location)
                loadSpmUrlMap.put(loadUrl,params)
            }
        }
    }

    override fun onReceivedSslError(
        view: WebView?,
        handler: SslErrorHandler?,
        error: SslError?
    ) {
        ConfirmDialog.Builder(ActivityStackManage.currentActivity())
            .setTitle("")
            .setMessage("SSL certificate validation failed.\n" + "Continue anyway?")
            .setCancelButton("Cancel"){ dialog, _ ->
                dialog.dismiss()
                handler?.cancel()
            }.setSureButton("Continue") { dialog, _ ->
                dialog.dismiss()
                handler?.proceed()
            }.setCanCancel(false).create().show()
    }

    override fun shouldInterceptRequest(
        view: WebView,
        request: WebResourceRequest
    ): WebResourceResponse? {
        //拦截资源加载
        var webResourceResponse: WebResourceResponse? =
            if (ifUseCache) WebCacheUtil.shouldInterceptRequest(view, request) else null
        if (webResourceResponse == null) {
            webResourceResponse = super.shouldInterceptRequest(view, request)
        }
        return webResourceResponse
    }

    /**
     * @param view 需要清理的WebView。
     * @param detail 退出的原因。。
     * @return true 如果主机应用程序处理了进程退出的情况，否则，如果渲染进程崩溃，应用程序将崩溃，或者如果渲染进程被系统杀死，则应用程序将被终止。
     */
    override fun onRenderProcessGone(
        view: WebView?,
        detail: RenderProcessGoneDetail?
    ): Boolean {
        if (view is JHWebView) {
            //解决部分机型Chrome内核偶现预加载Render Process
            return true
        }
        return super.onRenderProcessGone(view, detail)
    }

    fun putSpmLoadUrl(loadUrl:String){
        //默认所有加载的H5地址为code 200
        val params = mapOf("url" to loadUrl,"code" to "200")
        loadSpmUrlMap[loadUrl]=params
    }
    fun clearSpmLoadUrl(){
        loadSpmUrlMap.clear()
    }
}